home *** CD-ROM | disk | FTP | other *** search
/ Power CD-ROM!! 8 / Power CD-ROM 8.iso / prgmming / maxlib10 / maxlib.ref < prev    next >
Text File  |  1994-10-14  |  80KB  |  2,267 lines

  1.  
  2.  
  3.  
  4.  
  5.                    MAXLIB.REF
  6.                    ──────────────────────────────────────
  7.                    Technical Reference for MAXLIB For PB
  8.  
  9.  
  10.  
  11.  
  12.  
  13.  
  14.  
  15.  
  16.  
  17.  
  18.                                   Copyright 1994 Brian McLaughlin
  19.                      ────────────────────────────────────────────
  20.                                               All Rights Reserved
  21.  
  22.  
  23.  
  24.  
  25.  
  26.  
  27.  
  28.                          TABLE OF CONTENTS
  29.  
  30.  
  31.                                                        line number
  32.  
  33.    INTRODUCTION  ........................................   93
  34.  
  35.    SECTION ONE - MAXFiles Routines
  36.  
  37.      MAXFiles Routines  .................................  116
  38.      ClearX  ............................................  184
  39.      ClipX  .............................................  228
  40.      CloseX  ............................................  271
  41.      EndX%  .............................................  308
  42.      ErrorCode%  ........................................  342
  43.      FlushX  ............................................  369
  44.      GetLineX$  .........................................  411
  45.      GetLocX&  ..........................................  469
  46.      GetPtrBase%  .......................................  503
  47.      GetStX  ............................................  545
  48.      GetX  ..............................................  591
  49.      HandleX%  ..........................................  659
  50.      InitMAXFiles  ......................................  687
  51.      KillX  .............................................  736
  52.      LoadX  .............................................  763
  53.      OpenX%  ............................................  810
  54.      PutStX  ............................................  892
  55.      PutX  ..............................................  947
  56.      SaveLineX  ......................................... 1026
  57.      SaveX  ............................................. 1084
  58.      SetAccessCode  ..................................... 1147
  59.      SetBufferSize  ..................................... 1191
  60.      SetDiskFile  ....................................... 1233
  61.      SetErrorCode  ...................................... 1264
  62.      SetLocX  ........................................... 1288
  63.      SetPtrBase  ........................................ 1350
  64.      SizeX&  ............................................ 1393
  65.  
  66.  
  67.    SECTION TWO - MAXArray Routines
  68.  
  69.      MAXArray Routines .................................. 1430
  70.      ArrayInEMS  ........................................ 1487
  71.      ArrayOutEMS  ....................................... 1552
  72.      BytesFreeEMS&  ..................................... 1620
  73.      ClearEMS  .......................................... 1656
  74.      DimEMS%  ........................................... 1691
  75.      EraseEMS  .......................................... 1753
  76.      ErrorCode%  ........................................ 1784
  77.      FileInEMS  ......................................... 1814
  78.      FileOutEMS  ........................................ 1878
  79.      HandlesEMS%  ....................................... 1928
  80.      InEMS  ............................................. 1958
  81.      InitMAXArray  ...................................... 2009
  82.      LBoundEMS%  ........................................ 2060
  83.      OutEMS  ............................................ 2088
  84.      RedimEMS   (requires 4.0 EMM driver)  .............. 2134
  85.      SetErrorCode  ...................................... 2187
  86.      UBoundEMS%  ........................................ 2212
  87.      VersionEMS%  ....................................... 2238
  88.  
  89.  
  90.  
  91.  
  92.  
  93.     INTRODUCTION
  94.  
  95.  
  96.     This file (MAXLIB.REF) is the technical reference for MAXLIB For
  97.     PB.  It contains a complete detailed description of each routine
  98.     in MAXLIB For PB, including its DECLARE statement, a list of
  99.     parameters passed and a description of how the routine works.
  100.  
  101.     For further information about MAXLIB For PB (such as how it
  102.     handles errors) see the file MAXLIB.DOC.
  103.  
  104.     To use MAXLIB For PB you must have a copy of the PowerBASIC 3.0b
  105.     compiler or later.  I have tested MAXLIB For PB with the
  106.     PowerBASIC 3.0a release and found that because of bugs in that
  107.     compiler, MAXLIB For PB is not stable.
  108.  
  109.     PowerBASIC is a trademark of PowerBASIC, Inc of Carmel,
  110.     California.
  111.  
  112.  
  113.  
  114.  
  115.  
  116.     MAXFiles Routines
  117.     -----------------------------------------------------------------
  118.  
  119.  
  120.     MAXFiles can open or create files and store them in expanded
  121.     memory, where they can be accessed using methods similar to
  122.     those used for ordinary disk files.  If MAXFiles fails to find
  123.     sufficient expanded memory, it will use disk space instead,
  124.     allowing you to write code that will work on machines with or
  125.     without EMS.
  126.  
  127.     In order to use expanded memory, MAXFiles requires an EMM driver
  128.     that conforms to the LIM 4.0 EMS standard.  When no EMM driver
  129.     is present, or when an EMM driver is present but it has a
  130.     version number lower than 4.0, MAXFiles will not use expanded
  131.     memory, but will use disk space instead.
  132.  
  133.     The following is a list of MAXFiles routines along with their
  134.     closest counterparts in PowerBASIC:
  135.  
  136.  
  137.        OpenX% ................ OPEN (...FOR BINARY)
  138.        SetAccessCode ......... ACCESS LOCK/UNLOCK/READ/WRITE, etc.
  139.        CloseX ................ CLOSE# (close one open file)
  140.        ClearX ................ CLOSE  (close all open files)
  141.        PutX .................. PUT    (file statement)
  142.        GetX .................. GET    (file statement)
  143.        PutStX ................ PUT$
  144.        GetStX ................ GET$
  145.        SaveX ................. BSAVE
  146.        LoadX ................. BLOAD
  147.        GetLineX$ ............. LINE INPUT# (file statement)
  148.        EndX% ................. EOF
  149.        GetLocX& .............. SEEK   (as a function)
  150.        SetLocX ............... SEEK   (as a statement)
  151.        SizeX& ................ LOF
  152.        KillX ................. KILL
  153.        FlushX ................ FLUSH
  154.        ErrorCode% ............ ERR
  155.        SetErrorCode .......... ERROR
  156.        SetPtrBase ............ OPTION BASE
  157.  
  158.  
  159.     MAXFiles also includes the following commands that have no exact
  160.     equivalent in BASIC:
  161.  
  162.  
  163.        InitMAXFiles .......... initializes MAXFiles
  164.        ClipX ................. truncates a file
  165.        GetPtrBase% ........... returns value set by SetPtrBase
  166.        HandleX% .............. returns latest handle opened
  167.        SaveLineX ............. allows GetLineX to read multiple files
  168.        SetBufferSize ......... controls size of buffer for GetLineX
  169.        SetDiskFile ........... (dis/en)ables use of EMS memory
  170.  
  171.  
  172.     Although the routines in MAXFiles include some support for
  173.     networks, they have not been tested in a networked environment.
  174.     If you intend to use MAXLIB For PB on a network, you should test
  175.     your code thoroughly to ensure it is safe.
  176.  
  177.     The MAXFiles routines described in this section are in two object
  178.     files in MAXLIB.PBL, named MAXFILES.OBJ and SHARED.OBJ.
  179.  
  180.  
  181.  
  182.  
  183.  
  184.     ClearX
  185.     -----------------------------------------------------------------
  186.  
  187.     DECLARE SUB ClearX ()
  188.  
  189.     Parameters: none
  190.  
  191.  
  192.  
  193.     ClearX may be compared to CLOSE (without parameters) in BASIC,
  194.     with one very significant difference.  CLOSE closes all open
  195.     disk files, but ClearX only closes EMS files.  Calling ClearX
  196.     has no effect on open disk files.  This includes disk files that
  197.     were opened as EMS files, but later converted into disk files by
  198.     PutX, because of memory limitations.
  199.  
  200.  
  201.         ClearX
  202.  
  203.  
  204.     The above code closes all open files currently stored in
  205.     expanded memory.
  206.  
  207.     When ClearX is called, it steps through the internal table of
  208.     EMS files and systematically calls CloseX to close each of the
  209.     files it finds in that table.  All the actions described under
  210.     CloseX in regard to EMS files also apply to closing EMS files
  211.     with ClearX.
  212.  
  213.     Normally, InitMAXFiles registers ClearX with SetOnExit, so that
  214.     ClearX will be called automatically as part of your program's
  215.     exit code.
  216.  
  217.     SetOnExit is limited to a total of 8 routines that can be
  218.     registered in a single program.  If your program has already
  219.     used all 8 slots prior to calling InitMAXFiles, you should call
  220.     ClearX manually before ending your program.
  221.  
  222.     See also CloseX.
  223.  
  224.  
  225.  
  226.  
  227.  
  228.     ClipX
  229.     -----------------------------------------------------------------
  230.  
  231.     DECLARE SUB ClipX (Handle%, NewSize&)
  232.  
  233.     Parameters: Handle% = handle of file to truncate
  234.                 NewSize& = new size of file, in bytes, as long integer
  235.  
  236.  
  237.  
  238.     ClipX lets you truncate an opened file to the size you specify:
  239.  
  240.  
  241.        ClipX Handle%, 3500&
  242.  
  243.  
  244.     The above code shortens the file designated by Handle% to a
  245.     length of 3500 bytes, assuming the file was more than 3500 bytes
  246.     long.
  247.  
  248.     After a call to ClipX the file pointer will point to the first
  249.     byte immediately following the new end byte of the file.  In the
  250.     example above (assuming a zero-based file pointer), the first
  251.     byte of the file would be byte zero, the final byte of the file
  252.     would be byte 3499 and the pointer would be at byte 3500.
  253.  
  254.     IMPORTANT: If NewSize& is greater than the current size of the
  255.     file, ClipX will move the file pointer one byte beyond the
  256.     current end byte of the file, but the file will remain the same
  257.     size.
  258.  
  259.     If the file designated by Handle% is an EMS file, be aware that
  260.     when you call ClipX, any corresponding file on disk will be
  261.     truncated at the time of the call to ClipX.
  262.  
  263.     For more information about file pointers, see ABOUT FILE
  264.     POINTERS in MAXLIB.DOC.
  265.  
  266.     See also SetLocX.
  267.  
  268.  
  269.  
  270.  
  271.     CloseX
  272.     -----------------------------------------------------------------
  273.  
  274.     DECLARE SUB CloseX (Handle%)
  275.  
  276.     Parameters: Handle% = handle of file to close
  277.  
  278.  
  279.  
  280.     CloseX is a substitute for CLOSE #FileNum in BASIC.  It closes
  281.     one file opened by OpenX%.
  282.  
  283.  
  284.        CloseX Handle%
  285.  
  286.  
  287.     The above code closes the file designated by Handle%.  CloseX
  288.     will ignore any attempts to close a handle numbered 0-4.  Those
  289.     handles are reserved by DOS and closing them would be a mistake.
  290.  
  291.     When Handle% designates an EMS file, CloseX first checks to see
  292.     if the file has been altered since it was last opened or flushed
  293.     to disk.  If the file has been altered, CloseX will open the
  294.     corresponding disk file and save the new contents of the file to
  295.     disk before closing the file.  If the file has not been altered,
  296.     the file will not be saved to disk.
  297.  
  298.     Whether or not the file has been altered, CloseX will close
  299.     the appropriate entry in the internal table of EMS files and
  300.     deallocate the expanded memory occupied by the file, so it can
  301.     be used for other purposes.
  302.  
  303.     See also ClearX.
  304.  
  305.  
  306.  
  307.  
  308.     EndX
  309.     -----------------------------------------------------------------
  310.  
  311.     DECLARE FUNCTION EndX% ()
  312.  
  313.     Parameters: none
  314.  
  315.  
  316.     EndX% is a substitute for EOF.  It works in conjunction with
  317.     GetLineX$ only.  When GetLineX$ is processing a text file and
  318.     bytes remain to be read, EndX% returns a zero.  When GetLineX$
  319.     reaches the end of the file and no more bytes remain to be read,
  320.     EndX% returns -1.
  321.  
  322.  
  323.        DO
  324.          X% = X% + 1
  325.          Array$(X%) = GetLineX$(Handle%)
  326.        LOOP UNTIL EndX% OR ErrorCode%
  327.  
  328.  
  329.     The above code loads a variable length string array with lines
  330.     of text from the file designated by Handle%.  The loop will
  331.     iterate until the end of the file is reached, or an error
  332.     occurs.
  333.  
  334.     EndX% will not report the end of a file when a CHR$(26) is
  335.     encountered in a file.
  336.  
  337.     See also GetLineX$.
  338.  
  339.  
  340.  
  341.  
  342.     ErrorCode
  343.     -----------------------------------------------------------------
  344.  
  345.     DECLARE FUNCTION ErrorCode% ()
  346.  
  347.     Parameters: none
  348.  
  349.  
  350.     When an error occurs during any of the MAXLIB For PB routines,
  351.     the error is trapped (no action is taken by DOS or BASIC) and
  352.     the error code is stored in an internal variable.  This includes
  353.     critical errors.  The current contents of that variable are
  354.     returned by ErrorCode%.
  355.  
  356.  
  357.        IF ErrorCode% = 2 THEN PRINT "File not found!"
  358.  
  359.  
  360.     ErrorCode% may return some non-standard error codes (-1 to -4)
  361.     under certain conditions.  For more information see HANDLING
  362.     ERRORS in MAXLIB.DOC and the file ERRCODE.LST.
  363.  
  364.     See also SetErrorCode.
  365.  
  366.  
  367.  
  368.  
  369.     FlushX
  370.     -----------------------------------------------------------------
  371.  
  372.     DECLARE SUB FlushX (Handle%)
  373.  
  374.     Parameters: Handle% = handle of the file to flush to disk
  375.  
  376.  
  377.  
  378.     FlushX is a substitute for FLUSH.  Calling FlushX ensures that a
  379.     complete copy of the file is stored to disk immediately.  Files
  380.     that are flushed remain open.
  381.  
  382.     If Handle% designates a disk file, FlushX causes the contents of
  383.     the file buffers (maintained by DOS) to be written to disk.
  384.  
  385.     If Handle% designates a file stored in expanded memory, FlushX
  386.     will open the corresponding disk file, write the contents of the
  387.     file to disk and close the disk file.  Closing the disk file has
  388.     the added effect of flushing the DOS buffers.  The EMS file
  389.     remains open.
  390.  
  391.  
  392.         FlushX Handle%
  393.  
  394.  
  395.     The above code flushes the complete contents of the file
  396.     designated by Handle% onto disk.
  397.  
  398.     Flushing is important if you are working with highly valuable
  399.     data, because any data that is not fully written to disk is
  400.     vulnerable to loss when something disrupts the operation of the
  401.     computer running your program.
  402.  
  403.     For more information, see SAFEGUARDING YOUR DATA in MAXLIB.DOC.
  404.  
  405.     See also CloseX.
  406.  
  407.  
  408.  
  409.  
  410.  
  411.     GetLineX
  412.     -----------------------------------------------------------------
  413.  
  414.     DECLARE FUNCTION GetLineX$ (Handle%)
  415.  
  416.     Parameters: Handle% = the handle of the file to read from
  417.  
  418.  
  419.  
  420.     GetLineX$ is a substitute for LINE INPUT#.  It simplifies the
  421.     task of reading ASCII text files one line at time.
  422.  
  423.  
  424.        TextLine$ = GetLineX$(Handle%)
  425.  
  426.  
  427.     The above code returns one line of text from the file designated
  428.     by Handle%.  The line of text starts with the character at the
  429.     current file pointer and includes all characters up to but not
  430.     including the first carriage return character, or CHR$(13).  If
  431.     the first character encountered is a CHR$(13), GetLineX$ returns
  432.     a null string.
  433.  
  434.     The longest string GetLineX$ may return is 256 bytes.  When
  435.     GetLineX$ does not encounter a CHR$(13) within the first 256
  436.     characters it simply returns those 256 characters.
  437.  
  438.     GetLineX$ allocates a string to use as an internal buffer.  The
  439.     default size of this buffer is 8174 bytes.  When GetLineX$
  440.     detects the end of a file, it sets the value reported by EndX%
  441.     to -1 and it deallocates its buffer.
  442.  
  443.     If GetLineX$ fails to allocate a string to use as a buffer, it
  444.     will return a non-standard error code of -1.  One common way for
  445.     the buffer allocation to fail is if your code uses the
  446.     metacommand $STRING to set a string segment size smaller than
  447.     8K.  The default buffer size of 8174 bytes requires an 8K string
  448.     segment (or larger).
  449.  
  450.     If buffer allocation fails, or if you require a larger or
  451.     smaller buffer for other reasons, you may change the size of the
  452.     buffer.  See SetBufferSize for more details.
  453.  
  454.     Buffering requires GetLineX$ to maintain its own internal
  455.     pointer, which will rarely agree with the "regular" file
  456.     pointer.  For that reason, if you use GetLineX$ to read from
  457.     more than one file at once, you may need to use SaveLineX.  For
  458.     more details, see SaveLineX.
  459.  
  460.     GetLineX$ will not accept a handle for a DOS STDxx device (0-4).
  461.     If you call GetLineX$ with such a handle, it will simply return
  462.     a null string and report an "invalid handle" error (6).
  463.  
  464.     See also EndX%, GetStX.
  465.  
  466.  
  467.  
  468.  
  469.     GetLocX
  470.     -----------------------------------------------------------------
  471.  
  472.     DECLARE FUNCTION GetLocX& (Handle%)
  473.  
  474.     Parameters: Handle% = handle of file in which to find pointer
  475.  
  476.  
  477.  
  478.     GetLocX& is a substitute for the function form of SEEK.  It
  479.     returns a long integer representing the present position of the
  480.     file pointer within the file specified by Handle%:
  481.  
  482.  
  483.        PtrLoc& = GetLocX&(Handle%)
  484.  
  485.  
  486.     The above code returns the current position of the file pointer
  487.     in the file designated by Handle%.
  488.  
  489.     By default, the file is assumed to start at byte 0 (zero).  This
  490.     default may be changed to start at byte 1 by using the command
  491.     SetPtrBase.  See SetPtrBase or GetPtrBase for further details.
  492.  
  493.     If an error occurs during a call to GetLocX&, it returns a zero.
  494.     Normally, zero is a legal file pointer location.  To determine
  495.     with certainty whether an error has occured you must call
  496.     ErrorCode%.
  497.  
  498.     See also SetLocX.
  499.  
  500.  
  501.  
  502.  
  503.     GetPtrBase
  504.     -----------------------------------------------------------------
  505.  
  506.     DECLARE FUNCTION GetPtrBase% ()
  507.  
  508.     Parameters: none
  509.  
  510.  
  511.  
  512.     GetPtrBase% returns the base value used by GetLocX& and SetLocX:
  513.  
  514.  
  515.        Base% = GetPtrBase%
  516.  
  517.  
  518.     The above code returns the current pointer base value.  The
  519.     default value is zero, but you may change the value to 1, by
  520.     calling SetPtrBase.
  521.  
  522.     Normally, DOS defines the first byte of a file as byte 0 (zero).
  523.     However, when Microsoft introduced BINARY file handling into
  524.     BASIC, it chose to treat the first byte of a file as byte 1. To
  525.     accomodate code written for this convention, MAXFiles includes
  526.     the commands SetPtrBase and GetPtrBase%.
  527.  
  528.     When GetPtrBase% returns zero, MAXFiles is acting under the
  529.     zero-based (DOS) convention.  Under this convention, when the
  530.     pointer is at the second byte of a file, GetLocX& will return 1,
  531.     and if you want to set the pointer to the second byte you would
  532.     use SetLocX 1.
  533.  
  534.     When GetPtrBase% returns 1, MAXFiles is acting under the
  535.     one-based (Microsoft BASIC) convention.  Under this convention,
  536.     when the pointer is at the second byte of a file, GetLocX& will
  537.     return 2, and to set the pointer to the second byte you would
  538.     use SetLocX 2.
  539.  
  540.     See also SetPtrBase.
  541.  
  542.  
  543.  
  544.  
  545.     GetStX
  546.     -----------------------------------------------------------------
  547.  
  548.     DECLARE SUB GetStX (Handle%, ToString AS ANY)
  549.  
  550.     Parameters: Handle% = handle of the file to read from
  551.                 ToString = string to read data into
  552.  
  553.  
  554.  
  555.     GetStX is a substitute for GET$.  It lets you read from a file
  556.     into a variable length string or flex string.  Before calling
  557.     GetStX the string must be initialized to the length you want.
  558.     The length of the string determines the number of bytes GetStX
  559.     will read from the file into the string:
  560.  
  561.  
  562.        Target$ = SPACE$(100)
  563.        GetStX Handle%, Target$
  564.  
  565.  
  566.     In the above code, 100 bytes would be read from the file
  567.     specified by Handle% into Target$.  The file would be read
  568.     beginning at the current position of the file pointer.  GetStX
  569.     will advance the file pointer one byte for each byte read.
  570.  
  571.     If you try to read from a file when the file pointer is located
  572.     beyond its end, then GetStX will simply return with no action
  573.     taken and no error code.  If you try to read more bytes than lie
  574.     between the pointer and the end byte of the file, GetStX will
  575.     read as far as the end byte of the file and stop.
  576.  
  577.     If you want your program to read an ASCII text file (one which
  578.     uses a carriage return and linefeed to delimit each line of
  579.     text) you will probably want to use GetLineX$, rather than
  580.     GetStX.
  581.  
  582.     NOTE: When a parameter is declared AS ANY it must be passed as a
  583.     variable.  If you pass an equation, constant or literal value,
  584.     the compiler will report Error 426: Variable expected.
  585.  
  586.     See also PutStX.
  587.  
  588.  
  589.  
  590.  
  591.     GetX
  592.     -----------------------------------------------------------------
  593.  
  594.     DECLARE SUB GetX (Handle%, Bytes&, ToVariable AS ANY)
  595.  
  596.     Parameters: Handle% = the handle of the file to read from
  597.                 Bytes& = number of bytes to read
  598.                 ToVariable = the variable to read the data into
  599.  
  600.  
  601.  
  602.     GetX resembles GET, but is more powerful.  It allows you to read
  603.     Bytes& number of bytes from a file into a variable or into an
  604.     array.  You must specify the handle of the file to read from,
  605.     the number of bytes to read, and the variable to read into.  If
  606.     you are reading into an array, you need to specify the first
  607.     element of the range to be read into:
  608.  
  609.  
  610.        GetX Handle%, 4000&, Arry&(100)
  611.  
  612.  
  613.     The above example reads 4000 bytes from the file specified by
  614.     Handle% into Arry&() starting at element 100.
  615.  
  616.     IMPORTANT: Before using GetX with HUGE arrays, read the section
  617.     AVOIDING PROBLEMS WITH HUGE ARRAYS in MAXLIB.DOC.
  618.  
  619.     GetX always reads from the file starting at the position of the
  620.     file pointer.  GetX will automatically advance the file pointer
  621.     one byte forward for each byte it reads.  It is up to you to
  622.     make certain the file pointer is where you want it to be before
  623.     calling GetX.
  624.  
  625.     If you tell GetX to write more bytes than the target variable or
  626.     array can hold, it will overwrite whatever lies beyond the end
  627.     of your variable or array.  If you tell it to write too few
  628.     bytes, whatever "garbage" was in that area of RAM won't be fully
  629.     overwritten.  It is your responsibility to calculate the correct
  630.     number of bytes.
  631.  
  632.     If you try to read from a file when the file pointer is located
  633.     beyond its end, then GetX will simply return with no action
  634.     taken and no error code.  If you try to read more bytes than lie
  635.     between the pointer and the end byte of the file, GetX will read
  636.     as far as the end byte of the file and stop.
  637.  
  638.     If you pass GetX a value in Bytes& less than or equal to zero,
  639.     GetX will return without taking any action.  No error will be
  640.     reported.
  641.  
  642.     GetX can write to both variables or arrays of the following
  643.     types: fixed-length strings, numeric variables, and TYPE
  644.     variables.
  645.  
  646.     NOTE: When a parameter is declared AS ANY it must be passed as a
  647.     variable.  If you pass an equation, constant or literal value,
  648.     the compiler will report Error 426: Variable expected.
  649.  
  650.     GetX is NOT suitable for reading from files into variable length
  651.     strings, flex strings or arrays of such strings.  For these
  652.     strings you would use GetStX or GetLineX$.
  653.  
  654.     See also PutX.
  655.  
  656.  
  657.  
  658.  
  659.     HandleX
  660.     -----------------------------------------------------------------
  661.  
  662.     DECLARE FUNCTION HandleX% ()
  663.  
  664.     Parameters:  none
  665.  
  666.  
  667.     HandleX% returns the handle of the file most recently opened by
  668.     OpenX%.  Among other things it allows you to use the following
  669.     alternate logic when opening a file:
  670.  
  671.  
  672.        IF OpenX%(FileSpec$) THEN
  673.           Handle% = HandleX%      'get the handle for FileSpec$
  674.        ELSE
  675.           Call ErrorHandler
  676.        END IF
  677.  
  678.  
  679.     It is not recommended that you use HandleX% as a substitute for
  680.     a file handle variable.
  681.  
  682.     See also OpenX.
  683.  
  684.  
  685.  
  686.  
  687.     InitMAXFiles
  688.     -----------------------------------------------------------------
  689.  
  690.     DECLARE SUB InitMAXFiles ()
  691.  
  692.     Parameters: none
  693.  
  694.  
  695.     InitMAXFiles must be called once before using any of the other
  696.     routines listed in this section.  Calling it once is sufficient.
  697.     Calling InitMAXFiles more than once in the same program will
  698.     have no effect after the first call.
  699.  
  700.     When it is called, InitMAXFiles looks for an EMM driver on the
  701.     host computer.  If no driver is found, or if a driver is found
  702.     with a version number below 4.0, all files subsequently opened
  703.     by OpenX% will be ordinary disk files.
  704.  
  705.     If a version 4.0 or greater EMM driver is found, InitMAXFiles
  706.     determines how many entries to initialize in an internal table
  707.     of EMS files.  The maximum number of files MAXFiles can place
  708.     into expanded memory at one time is limited to the number of
  709.     entries in this table.
  710.  
  711.     When the table of EMS files is full, OpenX% can still open files
  712.     as disk files until all available DOS file handles are
  713.     exhausted.  However, it is important that you always leave at
  714.     least one DOS file handle unused, for internal use by MAXFiles.
  715.  
  716.     The default number of entries in this table is 32.  If
  717.     InitMAXFiles detects fewer than 32 EMS handles free, or fewer
  718.     than 32 pages of EMS memory free, the table will be initialized
  719.     to hold the smaller of these two values.
  720.  
  721.     Lastly, InitMAXFiles attempts to register ClearX as part of your
  722.     program's exit code, using the internal PowerBASIC procedure
  723.     called SetOnExit.  ClearX deallocates all the expanded memory
  724.     that is currently allocated by MAXFiles.
  725.  
  726.     SetOnExit is limited to a total of 8 routines that can be
  727.     registered in a single program.  If your program has already
  728.     used all 8 slots prior to calling InitMAXFiles, you should call
  729.     ClearX manually before ending your program.
  730.  
  731.     See also ClearX.
  732.  
  733.  
  734.  
  735.  
  736.     KillX
  737.     -----------------------------------------------------------------
  738.  
  739.     DECLARE SUB KillX (FileSpec$)
  740.  
  741.     Parameters: FileSpec$ = name of the file to kill (delete)
  742.  
  743.  
  744.  
  745.     KillX is a substitute for KILL.  It accepts a file name, which
  746.     may be up to 64 characters long and include a drive and
  747.     subdirectory path, but not wildcard characters:
  748.  
  749.  
  750.        FileName$ = "D:\PATH\FILENAME.EXT"   'no wildcards
  751.        KillX FileName$                      'delete the file
  752.  
  753.  
  754.     Do not try to kill a file when it is open.  Close it first using
  755.     CloseX.  If you kill a file when it is open MAXFiles will not
  756.     report an error, but you may end up with a mess, possibly
  757.     including cross-linked files that must be repaired by the DOS
  758.     CHKDSK command.
  759.  
  760.  
  761.  
  762.  
  763.     LoadX
  764.     -----------------------------------------------------------------
  765.  
  766.     DECLARE SUB LoadX (Handle%, Bytes&, ToSegment??)
  767.  
  768.     Parameters: Handle% = handle of the file to load data from
  769.                 Bytes& = number of bytes to load
  770.                 ToSegment?? = segment at which to load the data
  771.  
  772.  
  773.  
  774.     LoadX resembles BLOAD, but is more powerful.  Before you can
  775.     load a file with LoadX you must open it using OpenX%.  You pass
  776.     LoadX the handle of an opened file, the number of bytes to load,
  777.     and the segment address where you want them loaded.  It assumes
  778.     an offset of zero.
  779.  
  780.  
  781.        LoadX Handle%, 4000&, &HB800
  782.  
  783.  
  784.     The above code loads 4000 bytes from the file designated by
  785.     Handle% starting at the address &HB800:0000 (page zero of a
  786.     color monitor's video RAM, in text mode).
  787.  
  788.     You may set the file pointer wherever you wish before calling
  789.     LoadX, and therefore may read from the file at any point.  This
  790.     allows you to have more than one screen saved in a single file.
  791.  
  792.     If you try to read from the file when the pointer is located
  793.     beyond its end, then LoadX will simply return with no action
  794.     taken and no error code.  If you try to read more bytes than lie
  795.     between the pointer and the end byte of the file, LoadX will
  796.     read as far as the end byte of the file and stop.
  797.  
  798.     If the value in Bytes& is less than or equal to zero, LoadX will
  799.     return without taking any action.  No error will be reported.
  800.  
  801.     Unlike BLOAD, LoadX will not close the file for you.  You must
  802.     close it using CloseX.
  803.  
  804.     See also SaveX.
  805.  
  806.  
  807.  
  808.  
  809.  
  810.     OpenX
  811.     -----------------------------------------------------------------
  812.  
  813.     DECLARE FUNCTION OpenX% (FileSpec$)
  814.  
  815.     Parameters: FileSpec$ = name of the file to open or create
  816.  
  817.  
  818.  
  819.     OpenX% is a substitute for OPEN FOR BINARY.  It accepts a
  820.     FileName$ up to 64 characters long, which can include a drive
  821.     and path, but not wildcard characters.  OpenX% opens the file
  822.     named and returns the handle that you must use to access that
  823.     file, or a zero if there was an error:
  824.  
  825.  
  826.        FileName$ = "D:\PATH\FILENAME.EXT"   'no wildcards allowed
  827.        Handle% = OpenX%(FileName$)
  828.  
  829.  
  830.     When OpenX% opens a file, it sets the file access code according
  831.     to an internal variable.  This variable defaults to the code for
  832.     read-write access and network compatibility mode, but it may be
  833.     changed by making a call to SetAccessCode.
  834.  
  835.     If OpenX% can't find FileName$, it creates a zero-length, normal
  836.     attribute file of that name.  Created files are opened using the
  837.     current access code.  This requires OpenX% to create the file
  838.     first without the access code, close it and then immediately
  839.     reopen it using the access code.
  840.  
  841.     When OpenX% opens a file it must determine whether or not to
  842.     store the file in expanded memory.  When all of the following
  843.     conditions have been met, the file will be stored in EMS:
  844.  
  845.        1) an EMM driver was detected on the host machine, and
  846.        2) the EMM driver has a version number of at least 4.0, and
  847.        3) a free entry is available in the table of EMS files, and
  848.        4) you have not used SetDiskFile to force use of the disk, and
  849.        5) sufficient EMS is available to hold the entire file (if
  850.           the file is zero-length, one page of EMS must be free).
  851.  
  852.     When OpenX% stores a file in expanded memory, it reads a
  853.     complete copy of the file from disk into EMS and closes the disk
  854.     file.  This frees the DOS handle for further use.  Further
  855.     changes to the file will be reflected in the copy in EMS, but
  856.     will not normally be written to disk until the file is closed or
  857.     flushed.
  858.  
  859.     If the file was successfully stored in expanded memory, the
  860.     handle returned by OpenX% will be greater than 255.  If the file
  861.     is not stored in EMS, the handle will be an ordinary DOS file
  862.     handle.
  863.  
  864.     Handles returned for files stored in EMS are not the same as
  865.     handles issued by the EMM driver.  They are created by OpenX%
  866.     and refer to entries in an internal table of information
  867.     maintained by MAXFiles.
  868.  
  869.     When a file is first opened the file pointer always points to
  870.     the first byte of the file.  Normally, the first byte is
  871.     considered to be byte 0 (zero).  MAXFiles also lets you regard
  872.     this byte as byte 1. For more information, see SetPtrBase and
  873.     GetPtrBase%.
  874.  
  875.     If an error occurs during a call to OpenX%, it returns a zero
  876.     rather than a file handle.  Zero is a valid handle, but it is
  877.     reserved by DOS for STDIN.  If OpenX% returns a zero, don't use
  878.     it!  Instead, call ErrorCode%.
  879.  
  880.     When FileName$ is null or more than 64 characters, then OpenX%
  881.     treats these conditions as "file not found" errors.
  882.  
  883.     If FileName$ includes wildcard characters (?*) then your program
  884.     will crash!  Your program must trap this error before calling
  885.     OpenX%.
  886.  
  887.     See also CloseX.
  888.  
  889.  
  890.  
  891.  
  892.     PutStX
  893.     -----------------------------------------------------------------
  894.  
  895.     DECLARE SUB PutStX (Handle%, FromString AS ANY)
  896.  
  897.     Parameters: Handle% = handle of the file to write to
  898.                 FromString = string to write data from
  899.  
  900.  
  901.  
  902.     PutStX is a substitute for PUT$.  It allows you to write a
  903.     variable length string or flex string to a file:
  904.  
  905.  
  906.        St$ = "This is a test."
  907.        PutStX Handle%, St$
  908.  
  909.  
  910.     The above code writes St$ to the file designated by Handle%.
  911.     The string will be written starting at the current position of
  912.     the file pointer.  PutStX will advance the file pointer one byte
  913.     for each byte written.
  914.  
  915.     If the file pointer is anywhere but the end of the file, the
  916.     previous contents of the file will be overwritten as PutStX
  917.     writes the new bytes to those locations.  It is up to you to
  918.     make certain the file pointer is pointing where you want it,
  919.     before calling PutStX.
  920.  
  921.     If Handle% designates a file stored in expanded memory and not
  922.     enough expanded memory can be allocated to allow PutStX to write
  923.     the required number of bytes, PutStX will automatically convert
  924.     the file from an EMS file to a disk file.
  925.  
  926.     To convert a file from EMS to disk, PutStX must open the
  927.     corresponding disk file and write the contents of the file
  928.     currently stored in expanded memory to disk.  Also, the
  929.     corresponding entry in the table of EMS files is cleared and the
  930.     expanded memory occupied by the file is deallocated.
  931.  
  932.     IMPORTANT: When converting a file from EMS to disk, PutStX MUST
  933.     CHANGE THE HANDLE YOU PASSED IT!  If secondary copies of this
  934.     handle exist in your program, they must also be changed.  Trying
  935.     to access the file using the old handle will fail and probably
  936.     generate errors.
  937.  
  938.     NOTE: When a parameter is declared AS ANY it must be passed as a
  939.     variable.  If you pass an equation, constant or literal value,
  940.     the compiler will report Error 426: Variable expected.
  941.  
  942.     See also GetStX.
  943.  
  944.  
  945.  
  946.  
  947.     PutX
  948.     -----------------------------------------------------------------
  949.  
  950.     DECLARE SUB PutX (Handle%, Bytes&, FromVariable AS ANY)
  951.  
  952.     Parameters: Handle% = the handle of the file to write to
  953.                 Bytes& = number of bytes to write
  954.                 FromVariable = the variable to write the data from
  955.  
  956.  
  957.  
  958.     PutX resembles PUT, but is more powerful.  It allows you to
  959.     write Bytes& number of bytes from a variable or an array to a
  960.     disk file.  You pass PutX the handle of the file to write to,
  961.     the number of bytes to write and the variable to be written
  962.     from.  If you are writing from an array, pass PutX the first
  963.     element of the range to be written from:
  964.  
  965.  
  966.        PutX Handle%, 4000&, Arry&(100)
  967.  
  968.  
  969.     The above code writes 4000 bytes from Arry&(), starting at
  970.     element 100, into the file specified by Handle%.  PutX will
  971.     write to the file starting at the location of the file pointer.
  972.     The file pointer will advance one byte for each byte written.
  973.  
  974.     IMPORTANT: Before using PutX with HUGE arrays, read the section
  975.     AVOIDING PROBLEMS WITH HUGE ARRAYS in MAXLIB.DOC.
  976.  
  977.     If the file pointer is anywhere but the end of the file, the
  978.     previous contents of the file will be overwritten as PutX writes
  979.     the new bytes to those locations.  It is up to you to make
  980.     certain the file pointer is pointing where you want it, before
  981.     calling PutX.
  982.  
  983.     If Handle% designates a file stored in expanded memory and not
  984.     enough expanded memory can be allocated to allow PutX to write
  985.     the required number of bytes, PutX will automatically convert
  986.     the file from an EMS file to a disk file.
  987.  
  988.     To convert a file from EMS to disk, PutX must open the
  989.     corresponding disk file and write the contents of the file
  990.     currently stored in expanded memory to disk.  Also, the
  991.     corresponding entry in the internal table of EMS files is
  992.     cleared and the expanded memory occupied by the file is
  993.     deallocated.
  994.  
  995.     IMPORTANT: When converting a file from EMS to disk, PutX MUST
  996.     CHANGE THE HANDLE YOU PASSED IT!  If secondary copies of this
  997.     handle exist in your program, they must also be changed.  Trying
  998.     to access the file using the old handle will fail and probably
  999.     generate errors.
  1000.  
  1001.     PutX will ignore any attempt to write zero bytes.  This is
  1002.     because writing zero bytes has the (sometimes traumatic) effect
  1003.     of truncating a disk file.  If you desire this effect, see
  1004.     ClipX.
  1005.  
  1006.     If you pass PutX a negative value in Bytes&, PutX will also
  1007.     ignore it and return without taking action.  No error will be
  1008.     declared.
  1009.  
  1010.     NOTE: When a parameter is declared AS ANY it must be passed as a
  1011.     variable.  If you pass an equation, constant or literal value,
  1012.     the compiler will report Error 426: Variable expected.
  1013.  
  1014.     PutX can write variables or arrays of the following types:
  1015.     fixed-length strings, numeric variables or TYPE variables.
  1016.  
  1017.     PutX is NOT suitable for use with variable length strings, flex
  1018.     strings, or arrays of such strings.  Instead, see PutStX.
  1019.  
  1020.     See also GetX.
  1021.  
  1022.  
  1023.  
  1024.  
  1025.  
  1026.     SaveLineX
  1027.     -----------------------------------------------------------------
  1028.  
  1029.     DECLARE SUB SaveLineX ()
  1030.  
  1031.     Parameters: none
  1032.  
  1033.  
  1034.  
  1035.     SaveLineX resets the file pointer of the file most recently read
  1036.     by GetLineX$ to match the internal file pointer maintained by
  1037.     GetLineX$.  SaveLineX is only needed under the following
  1038.     conditions:
  1039.  
  1040.       1) GetLineX$ has not finished reading file A to the end, and
  1041.       2) you must use GetLineX$ to read from a second file B, and
  1042.       3) you must return later to file A at the point you left off.
  1043.  
  1044.     Whenever these three conditions exist, you must call SaveLineX
  1045.     after your latest read from file A and before reading from file
  1046.     B, as in the following example:
  1047.  
  1048.  
  1049.        DO
  1050.           INCR LineCount%
  1051.  
  1052.           LineA$ = GetLineX$(A%)
  1053.             SaveLineX
  1054.             EndA% = EndX%
  1055.           LineB$ = GetLineX$(B%)
  1056.             SaveLineX
  1057.             EndB% = EndX%
  1058.  
  1059.           IF LineA$ <> LineB$ THEN
  1060.             PRINT "Lines"; LineCount%; " in A and B don't match."
  1061.           END IF
  1062.  
  1063.        LOOP UNTIL EndA% OR EndB%
  1064.  
  1065.  
  1066.     SaveLineX always resets the pointer of the file whose handle was
  1067.     last passed to GetLineX$.  If you call SaveLineX prior to your
  1068.     first call to GetLineX$, it will cause an "invalid handle"
  1069.     error.  If you have closed the file most recently read by
  1070.     GetLineX$, you will also get the same error.
  1071.  
  1072.     NOTE: Alternating line-by-line between files, as in the example
  1073.     above, causes GetLineX$ to repeatedly empty and refill its
  1074.     buffer, causing it to slow down significantly.  It would be much
  1075.     faster to use GetLineX$ to read each file into its own array and
  1076.     then to compare the lines afterward.
  1077.  
  1078.     See also GetLineX.
  1079.  
  1080.  
  1081.  
  1082.  
  1083.  
  1084.     SaveX
  1085.     -----------------------------------------------------------------
  1086.  
  1087.     DECLARE SUB SaveX (Handle%, Bytes&, FromSegment??)
  1088.  
  1089.     Parameters: Handle% = handle of the file to write to
  1090.                 Bytes& = number of bytes to write
  1091.                 FromSegment?? = segment to save data from
  1092.  
  1093.  
  1094.  
  1095.     SaveX resembles BSAVE, but is more powerful.  It allows you to
  1096.     read from a memory location, such as video memory, directly into
  1097.     a file.  Notice that SaveX only lets you to pass the segment
  1098.     portion of the address from which you want data saved.  It
  1099.     assumes an offset of zero.
  1100.  
  1101.  
  1102.        SaveX Handle%, 4000&, &HB800
  1103.  
  1104.  
  1105.     In the above code, the 4000 bytes starting at &HB800:0000 (page
  1106.     zero of a color monitor's video RAM in text mode) will be
  1107.     written to the file designated by Handle%, starting at the
  1108.     current position of the file pointer.
  1109.  
  1110.     Before you can save to a file using SaveX, you must open the
  1111.     file using OpenX%.  Also, SaveX will not close the file for you.
  1112.     You must close the file seperately, using CloseX, when you are
  1113.     done with it.
  1114.  
  1115.     You may use SaveX to write more than 64K bytes at once.  Also,
  1116.     you may append data onto the end of an existing file, so you may
  1117.     have as many screens full of information as you wish in a single
  1118.     file.
  1119.  
  1120.     If Handle% designates a file stored in expanded memory and not
  1121.     enough expanded memory can be allocated to allow SaveX to write
  1122.     the required number of bytes, SaveX will automatically convert
  1123.     the file from an EMS file to a disk file.
  1124.  
  1125.     To convert a file from EMS to disk, SaveX must open the
  1126.     corresponding disk file and write the contents of the file
  1127.     currently stored in expanded memory to disk.  Also, the
  1128.     corrseponding entry in the table of EMS files is cleared and the
  1129.     expanded memory occupied by the file is deallocated.
  1130.  
  1131.     IMPORTANT: When converting a file from EMS to disk, SaveX MUST
  1132.     CHANGE THE HANDLE YOU PASSED IT!  If secondary copies of this
  1133.     handle exist in your program, they must also be changed.  Trying
  1134.     to access the file using the old handle will fail and probably
  1135.     generate errors.
  1136.  
  1137.     If the value in Bytes& is less than or equal to zero, SaveX will
  1138.     return without taking any action.  No error will be reported.
  1139.  
  1140.     SaveX does NOT add a header to your files, as BSAVE does.
  1141.  
  1142.     See also LoadX.
  1143.  
  1144.  
  1145.  
  1146.  
  1147.     SetAccessCode
  1148.     -----------------------------------------------------------------
  1149.  
  1150.     DECLARE SUB SetAccessCode (AccessCode%)
  1151.  
  1152.     Parameters: AccessCode% = access code to use in opening files
  1153.  
  1154.  
  1155.  
  1156.     SetAccessCode sets the file access code used by OpenX% when
  1157.     opening files:
  1158.  
  1159.  
  1160.        SetAccessCode 0
  1161.        Handle% = OpenX%(FileName$)
  1162.  
  1163.  
  1164.     The above code opens FileName$ with a read-only access code.
  1165.     This is not the same as giving the file a read-only attribute.
  1166.     When you set a new access code using SetAccessCode, all
  1167.     subsequent calls to OpenX% will use the new access code.
  1168.  
  1169.     These BASIC commands are equivalent to the following access
  1170.     codes:
  1171.  
  1172.  
  1173.        ACCESS READ WRITE  ...  2
  1174.        ACCESS READ    .......  0
  1175.        ACCESS WRITE   .......  1
  1176.        ACCESS READ SHARED ...  64
  1177.        LOCK READ      .......  50
  1178.        LOCK WRITE     .......  34
  1179.  
  1180.  
  1181.     IMPORTANT: MAXFiles has not been tested in a networked
  1182.     environment.  If you use MAXFiles in a network, you should test
  1183.     it until you are satisfied it is safe.
  1184.  
  1185.     For more complete information about access codes, consult a DOS
  1186.     reference.
  1187.  
  1188.  
  1189.  
  1190.  
  1191.     SetBufferSize
  1192.     -----------------------------------------------------------------
  1193.  
  1194.     DECLARE SUB SetBufferSize (Bytes%)
  1195.  
  1196.     Parameters: Bytes% = number of bytes to use for buffer
  1197.  
  1198.  
  1199.  
  1200.     SetBufferSize lets you change the size of the buffer allocated
  1201.     by GetLineX$.  The default buffer size is 8174 bytes.
  1202.  
  1203.  
  1204.        SetBufferSize 5000
  1205.  
  1206.  
  1207.     The example above sets the buffer size to 5000 bytes.
  1208.  
  1209.     If you try to set the buffer size above 32750 bytes or below
  1210.     1006 bytes, SetBufferSize will round the buffer size up or down
  1211.     to match the nearest of these limits.
  1212.  
  1213.     Because the buffer allocated by GetLineX$ is a string, it is
  1214.     affected by the string segment size set by $STRING.  The largest
  1215.     string that can be allocated within a string segment is the size
  1216.     of the segment minus 18 bytes.
  1217.  
  1218.     For example, if the example code above were preceeded by the
  1219.     metacommand $STRING 4, the buffer of 5000 bytes would not fit
  1220.     inside the 4K string segment, causing GetLineX$ to fail.  You
  1221.     would need to set the buffer size to between 4078 and 1006 bytes
  1222.     before your first call to GetLineX$ to compensate for the
  1223.     $STRING 4 statement.
  1224.  
  1225.     When GetLineX$ fails to allocate a buffer string, it returns the
  1226.     non-standard error code -1.
  1227.  
  1228.     See also GetLineX.
  1229.  
  1230.  
  1231.  
  1232.  
  1233.     SetDiskFile
  1234.     -----------------------------------------------------------------
  1235.  
  1236.     DECLARE SUB SetDiskFile (Switch%)
  1237.  
  1238.     Parameters: Switch% = non-zero value disables use of EMS
  1239.  
  1240.  
  1241.  
  1242.     SetDiskFile allows you to control whether OpenX% attempts to use
  1243.     expanded memory when opening files.  By default, OpenX% will
  1244.     always attempt to open a file as an EMS file first, then fall
  1245.     back to disk in the event the file could not be opened in EMS.
  1246.  
  1247.     Calling SetDiskFIle with a non-zero value in Switch% will ensure
  1248.     that all files opened subsequently by OpenX% will be disk files.
  1249.     Calling SetDiskFile with a zero value in Switch% re-enables the
  1250.     use of expanded memory.
  1251.  
  1252.  
  1253.        %DISK = -1
  1254.        SetDiskFile %DISK
  1255.  
  1256.  
  1257.     The above code disables the use of expanded memory by OpenX%.
  1258.  
  1259.     See also OpenX.
  1260.  
  1261.  
  1262.  
  1263.  
  1264.     SetErrorCode
  1265.     -----------------------------------------------------------------
  1266.  
  1267.     DECLARE SUB SetErrorCode (ErrorCode%)
  1268.  
  1269.     Parameters: ErrorCode% = value to place into internal error code
  1270.  
  1271.  
  1272.  
  1273.     SetErrorCode allows you to reset the error code reported by
  1274.     ErrorCode% to any integer value:
  1275.  
  1276.  
  1277.        SetErrorCode 2    'set the new error code
  1278.        PRINT ErrorCode%  'will always print "2"
  1279.  
  1280.  
  1281.     For more information see HANDLING ERRORS in MAXLIB.DOC.
  1282.  
  1283.     See also ErrorCode.
  1284.  
  1285.  
  1286.  
  1287.  
  1288.     SetLocX
  1289.     -----------------------------------------------------------------
  1290.  
  1291.     DECLARE SUB SetLocX (Handle%, NewPtrLoc&)
  1292.  
  1293.     Parameters: Handle% = handle of file whose ptr will be reset
  1294.                 NewPtrLoc& = new location of pointer in the file
  1295.  
  1296.  
  1297.  
  1298.     SetLocX is a substitute for the statement form of SEEK.  You
  1299.     pass it the handle of the file whose pointer you want to set and
  1300.     the location of the byte where you want to set the file pointer
  1301.     (as an offset from the start of the file):
  1302.  
  1303.  
  1304.        SetLocX Handle%, 9000&
  1305.  
  1306.  
  1307.     The above code moves the file pointer in the file designated by
  1308.     Handle% to byte number 9000.  If subsequently you were to read
  1309.     from the file, byte 9000 would be the first byte read.  If you
  1310.     were to write to the file, byte 9000 would be the first byte
  1311.     written to.
  1312.  
  1313.     If you are unfamiliar with file pointers, see ABOUT FILE
  1314.     POINTERS in MAXLIB.DOC.
  1315.  
  1316.     How SetLocX interprets the value of NewPtrLoc& may vary,
  1317.     depending on whether you have made a call to SetPtrBase.  By
  1318.     default, MAXFiles considers the first byte of a file to be byte
  1319.     zero.  However, you may change this default to a 1-based system,
  1320.     using SetPtrBase.  Please see SetPtrBase for more details.
  1321.  
  1322.     It is possible to move the file pointer many bytes beyond the
  1323.     "end" byte of a disk file.  This is a valid position at which to
  1324.     write to a disk file -- in which case the disk file will be
  1325.     extended to include all the bytes falling between the previous
  1326.     "end" of the disk file and the byte where the pointer was
  1327.     located when the writing was initiated.
  1328.  
  1329.     IMPORTANT: If the file designated by Handle% is an EMS file
  1330.     rather than a disk file (EMS files have handles greater than
  1331.     255) and NewPtrLoc& exceeds the size of the file plus the value
  1332.     of the pointer base, SetPtrLoc will move the pointer only as far
  1333.     as the byte immediately following the end byte of the file.
  1334.     This allows you to move the pointer to the correct byte at which
  1335.     to append data directly to the end of the file, but no further.
  1336.     This restriction does not apply to disk files.
  1337.  
  1338.     If you try to read from a file when the pointer is located
  1339.     beyond its end, then MAXFiles will simply return with no action
  1340.     taken and no error code.  If you try to read more bytes than lie
  1341.     between the pointer and the end byte of the file, MAXFiles will
  1342.     read as far as the end byte of the file and stop.
  1343.  
  1344.     See also GetLocX.
  1345.  
  1346.  
  1347.  
  1348.  
  1349.  
  1350.     SetPtrBase
  1351.     -----------------------------------------------------------------
  1352.  
  1353.     DECLARE SUB SetPtrBase (PtrBase%)
  1354.  
  1355.     Parameters: PtrBase% = non-zero value sets pointer base to 1
  1356.  
  1357.  
  1358.  
  1359.     SetPtrBase sets the base value used by GetLocX& and SetLocX:
  1360.  
  1361.  
  1362.        SetPtrBase 1     'sets pointer base to 1
  1363.  
  1364.  
  1365.     Calling SetPtrBase with a zero sets the pointer base to zero.
  1366.     Calling SetPtrBase with any non-zero value sets the base value
  1367.     to 1. The default base value is zero.
  1368.  
  1369.     Normally, DOS defines the first byte of a file as byte 0 (zero).
  1370.     However, when Microsoft introduced BINARY file handling into
  1371.     BASIC, it chose to treat the first byte of a file as byte 1. To
  1372.     accomodate code written for this convention, MAXFiles includes
  1373.     the commands SetPtrBase and GetPtrBase%.
  1374.  
  1375.     If you call SetPtrBase with a zero, MAXFiles will act under the
  1376.     zero-based (DOS) convention.  This is also the MAXFiles default.
  1377.     Under this convention, when the pointer is at the second byte of
  1378.     a file, GetLocX& will return 1, and if you want to set the
  1379.     pointer to the second byte you would use SetLocX 1.
  1380.  
  1381.     If you call SetPtrBase with a non-zero value, MAXFiles will act
  1382.     under the one-based (Microsoft BASIC) convention.  Under this
  1383.     convention, when the pointer is at the second byte of a file,
  1384.     GetLocX& will return 2, and to set the pointer to the second
  1385.     byte you would use SetLocX 2.
  1386.  
  1387.     See also GetPtrBase.
  1388.  
  1389.  
  1390.  
  1391.  
  1392.  
  1393.     SizeX
  1394.     -----------------------------------------------------------------
  1395.  
  1396.     DECLARE FUNCTION SizeX& (Handle%)
  1397.  
  1398.     Parameters: Handle% = handle of file whose size you want
  1399.  
  1400.  
  1401.  
  1402.     SizeX& is a substitute for LOF.  It returns the length of a file
  1403.     that has been opened with OpenX%, as a long integer:
  1404.  
  1405.  
  1406.        HowBig& = SizeX&(Handle%)
  1407.  
  1408.  
  1409.     In the above code, SizeX& returns the size of the file
  1410.     designated by Handle% and assigns the value to the variable
  1411.     HowBig&.
  1412.  
  1413.     If an error occurs, SizeX& returns a zero.  Since zero is also a
  1414.     valid file length the only way to determine certainly if an
  1415.     error has occured is to call ErrorCode%.
  1416.  
  1417.  
  1418.  
  1419.  
  1420.     ********************************************************************
  1421.  
  1422.                      END OF SECTION ONE:  MAXFILES
  1423.  
  1424.     ********************************************************************
  1425.  
  1426.  
  1427.  
  1428.  
  1429.  
  1430.     MAXArray Routines
  1431.     -----------------------------------------------------------------
  1432.  
  1433.  
  1434.     MAXArray can be used to create arrays in EMS to hold any
  1435.     variables having a fixed length.  This includes all numeric
  1436.     variables (such as DOUBLE, LONG or BCD) and TYPE variables.  It
  1437.     also includes fixed-length strings.
  1438.  
  1439.     Arrays created with MAXArray cannot be used with variable
  1440.     length strings or flex strings.
  1441.  
  1442.     MAXArray allows you to create data arrays up to the full amount
  1443.     of expanded memory available on the host computer.  Normally,
  1444.     the maximum number of arrays MAXArray can dimension at once is
  1445.     32. This may be lower, if few EMS resources are available.
  1446.  
  1447.     Except for RedimEMS, all the routines in MAXArray will work
  1448.     under any EMM driver, starting with v3.0.  RedimEMS requires a
  1449.     v4.0 EMM driver.
  1450.  
  1451.     The following is a list of the MAXFiles routines that have close
  1452.     counterparts in PowerBASIC:
  1453.  
  1454.  
  1455.        DimEMS% ............... DIM
  1456.        InEMS ................. Array(Index) = Variable
  1457.        OutEMS ................ Variable = Array(Index)
  1458.        EraseEMS .............. ERASE
  1459.        RedimEMS .............. REDIM
  1460.        LBoundEMS% ............ LBOUND
  1461.        UBoundEMS% ............ UBOUND
  1462.        BytesFreeEMS& ......... FRE
  1463.        ErrorCode% ............ ERR
  1464.        SetErrorCode .......... ERROR
  1465.  
  1466.  
  1467.     In addition to these, MAXArray has a number of routines that
  1468.     have no counterpart in PowerBASIC:
  1469.  
  1470.  
  1471.        InitMAXArray .......... initializes MAXArray routines
  1472.        ArrayInEMS ............ copies conventional array to EMS
  1473.        ArrayOutEMS ........... copies EMS to conventional array
  1474.        ClearEMS .............. erases/deallocates all EMS arrays
  1475.        FileInEMS ............. copies file to EMS array
  1476.        FileOutEMS ............ copies EMS array to file
  1477.        HandlesEMS% ........... returns number of free array handles
  1478.        VersionEMS% ........... returns version number of EMM driver
  1479.  
  1480.  
  1481.     The MAXArray routines described in this section are in two
  1482.     object files in MAXLIB.PBL, named MAXARRAY.OBJ and SHARED.OBJ.
  1483.  
  1484.  
  1485.  
  1486.  
  1487.     ArrayInEMS
  1488.     -----------------------------------------------------------------
  1489.  
  1490.     DECLARE SUB ArrayInEMS (Handle%, FirstElement AS ANY)
  1491.  
  1492.     Parameters: Handle% = handle of the EMS array to copy into
  1493.                 FirstElement = first element of array to copy from
  1494.  
  1495.  
  1496.     This routine copies a conventional array into an array in EMS
  1497.     memory.  Handle% designates the EMS array to copy the data into,
  1498.     which will normally have the same characteristics and same size
  1499.     as the conventional array you want to copy from.  FirstElement
  1500.     is generally assumed to be the first element of the conventional
  1501.     array you want to copy, but that is not required.
  1502.  
  1503.     IMPORTANT: If the conventional array to be copied into the EMS
  1504.     array is a HUGE array with an element size which is not a power
  1505.     of two (not 2,4,8,16...etc.), then you cannot use ArrayInEMS.
  1506.     Instead, you must copy the array one element at a time in a
  1507.     loop, using InEMS.  See AVOIDING PROBLEMS WITH HUGE ARRAYS in
  1508.     MAXLIB.DOC for further details.
  1509.  
  1510.  
  1511.        DIM PBArray (100 TO 350) AS DOUBLE 'create an array of doubles
  1512.        .                                  'fill it with data here
  1513.        .
  1514.        EMSArray% = DimEMS%(100, 350, 8)   'create a similar EMS array
  1515.        ArrayInEMS EMSArray%, PBArray(100) 'copy PBArray into EMSArray
  1516.  
  1517.  
  1518.     The above code dimensions arrays in both conventional memory and
  1519.     EMS, then copies the conventional array into the EMS array.
  1520.  
  1521.     In this example, EMSArray% was dimensioned with the same first
  1522.     index (100) and last index (350) and same element length (8
  1523.     bytes) as PBArray.  This is recommended, but not required.
  1524.  
  1525.     ArrayInEMS treats the parameter FirstElement purely as the
  1526.     address in conventional memory from which to start copying as
  1527.     many bytes as the EMS array was dimensioned to hold.
  1528.  
  1529.     If the EMS array is smaller than the conventional array, only
  1530.     part of the conventional array will be copied.  If the EMS array
  1531.     is larger than the conventional array, some excess bytes will be
  1532.     copied into the final elements of the EMS array from the memory
  1533.     just beyond the end of the conventional array.
  1534.  
  1535.     ArrayInEMS will not prevent you from copying a conventional
  1536.     array into an EMS array having a different element length.
  1537.     However, the data will probably appear garbled when you try to
  1538.     access individual elements.
  1539.  
  1540.     This routine may generate a non-standard error code of -3, if
  1541.     the EMSHandle% parameter you pass it is an invalid handle.
  1542.  
  1543.     NOTE: When a parameter is declared AS ANY it must be passed as a
  1544.     variable.  If you pass an equation, constant or literal value,
  1545.     the compiler will report Error 426: Variable expected.
  1546.  
  1547.     See also ArrayOutEMS.
  1548.  
  1549.  
  1550.  
  1551.  
  1552.     ArrayOutEMS
  1553.     -----------------------------------------------------------------
  1554.  
  1555.     DECLARE SUB ArrayOutEMS (Handle%, FirstElement AS ANY)
  1556.  
  1557.     Parameters: Handle% = handle of the EMS array from which to copy
  1558.                 FirstElement = first element of the array to copy into
  1559.  
  1560.  
  1561.     This routine copies an array from EMS memory into an array in
  1562.     conventional memory.  Handle% designates the EMS array to be
  1563.     copied.  FirstElement is generally assumed to be the first
  1564.     element of a conventional array having the same characteristics
  1565.     and size as the EMS array, but this is not strictly required.
  1566.  
  1567.     IMPORTANT: If the conventional array into which you are copying
  1568.     the EMS array is a HUGE array with an element size which is not
  1569.     a power of two (not 2,4,8,16...etc.), then you cannot use
  1570.     ArrayOutEMS.  Instead, you must copy the array one element at a
  1571.     time, using OutEMS.  See AVOIDING PROBLEMS WITH HUGE ARRAYS in
  1572.     MAXLIB.DOC for further details.
  1573.  
  1574.  
  1575.        EMSArray% = DimEMS%(100, 350, 8)   'dim array to hold doubles
  1576.        .                                  'EMSArray filled with data
  1577.        .
  1578.        DIM PBArray (100 TO 350) AS DOUBLE 'dim an array to copy into
  1579.        ArrayOutEMS EMSArray%, PBArray(100) 'copy EMSArray into PBArray
  1580.  
  1581.  
  1582.     The above code dimensions arrays in both conventional memory and
  1583.     EMS, then copies the EMS array into the conventional array.
  1584.  
  1585.     In this example code, PBArray was dimensioned with the same
  1586.     first index (100) and last index (350) and same element length
  1587.     (DOUBLE = 8 bytes) as the array designated by EMSArray%.  This
  1588.     is recommended, but not required.
  1589.  
  1590.     ArrayOutEMS treats the parameter FirstElement purely as the
  1591.     address in conventional memory where it will start to copy the
  1592.     number of bytes the EMS array was dimensioned to hold.  If the
  1593.     EMS array is smaller than the conventional array into which it
  1594.     will be copied, the excess elements in the conventional array
  1595.     will retain whatever values they had before calling ArrayOutEMS.
  1596.  
  1597.     WARNING: If the EMS array you want to copy is larger than the
  1598.     conventional array into which it will be copied, the excess
  1599.     bytes from the EMS array will overwrite the memory beyond the
  1600.     end of the conventional array, corrupting that memory and
  1601.     probably losing your valuable data.
  1602.  
  1603.     ArrayOutEMS will not prevent you from copying an EMS array into
  1604.     a conventional array having a different element length.
  1605.     However, the data will probably appear garbled when you try to
  1606.     access individual elements.
  1607.  
  1608.     This routine may generate a non-standard error code of -3, if
  1609.     the EMSHandle% parameter you pass it is an invalid handle.
  1610.  
  1611.     NOTE: When a parameter is declared AS ANY it must be passed as a
  1612.     variable.  If you pass an equation, constant or literal value,
  1613.     the compiler will report Error 426: Variable expected.
  1614.  
  1615.     See also ArrayInEMS.
  1616.  
  1617.  
  1618.  
  1619.  
  1620.     BytesFreeEMS&
  1621.     -----------------------------------------------------------------
  1622.  
  1623.     DECLARE FUNCTION BytesFreeEMS& ()
  1624.  
  1625.     Parameters: none
  1626.  
  1627.  
  1628.     This routine returns the number of bytes of unallocated EMS
  1629.     memory, as a long integer.
  1630.  
  1631.  
  1632.         FreeEMS& = BytesFreeEMS&
  1633.  
  1634.  
  1635.     The above code returns the number of bytes of unallocated EMS
  1636.     memory.  This is not the same as the number of bytes of EMS
  1637.     memory installed.
  1638.  
  1639.     BytesFreeEMS& will return a zero if any of the following
  1640.     conditions are met:
  1641.  
  1642.       1) all EMS memory has already been allocated, or
  1643.       2) no EMS driver is installed, or
  1644.       3) an error occured, or
  1645.       4) InitMAXArray was not called before calling BytesFreeEMS&.
  1646.  
  1647.  
  1648.     The number of bytes of free EMS memory will always be a multiple
  1649.     of 16384 (16K).
  1650.  
  1651.     See also HandlesEMS%.
  1652.  
  1653.  
  1654.  
  1655.  
  1656.     ClearEMS
  1657.     -----------------------------------------------------------------
  1658.  
  1659.     DECLARE SUB ClearEMS ()
  1660.  
  1661.     Parameters: none
  1662.  
  1663.  
  1664.     This routine erases all EMS arrays currently allocated through
  1665.     DimEMS.  It does this by stepping through an internal table of
  1666.     array information and deallocating every array it finds there.
  1667.  
  1668.     ClearEMS will not deallocate EMS memory that was allocated by
  1669.     other programs, or by calls made directly to the EMM driver.
  1670.     Only memory allocated by DimEMS or RedimEMS will be deallocated.
  1671.  
  1672.     The data in arrays cleared by ClearEMS cannot be retrieved, so
  1673.     be cautious when calling ClearEMS.
  1674.  
  1675.     Deallocation is important, because (unlike conventional RAM) EMS
  1676.     memory stays allocated when the program that allocated it ends.
  1677.     For that reason, if you forget to deallocate EMS memory before
  1678.     ending your program that EMS memory cannot be used by other
  1679.     programs.
  1680.  
  1681.     To help you avoid this problem, InitMAXArray registers ClearEMS
  1682.     as part of the exit code performed automatically when your
  1683.     program ends.  More details can be found under InitMAXArray.
  1684.  
  1685.     See also EraseEMS.
  1686.  
  1687.  
  1688.  
  1689.  
  1690.  
  1691.     DimEMS%
  1692.     -----------------------------------------------------------------
  1693.  
  1694.     DECLARE FUNCTION DimEMS% (FirstIndex%, LastIndex%, ElementLen%)
  1695.  
  1696.     Parameters:  FirstIndex% = first element number in array
  1697.                  LastIndex% = last element number in array
  1698.                  ElementLen% = fixed length of each element
  1699.  
  1700.  
  1701.     This routine allocates an array in EMS memory large enough to
  1702.     hold the requested number of elements and returns a handle that
  1703.     your program must use to access that array.  The following two
  1704.     lines of code are comparable:
  1705.  
  1706.  
  1707.        DIM ArrayName (50:1000) AS STRING * 200  'BASIC array
  1708.        ArrayName% = DimEMS%(50, 1000, 200)      'EMS array
  1709.  
  1710.  
  1711.     DimEMS will never return zero as a valid handle for an array,
  1712.     but DimEMS does return a zero if it fails to dimension an array.
  1713.     DimEMS may return a zero under any of the following conditions:
  1714.  
  1715.        1) insufficient EMS memory is available, or
  1716.        2) no space is available in the table of array info, or
  1717.        3) no EMM driver was detected by InitMAXArray, or
  1718.        4) InitMAXArray was not called before calling DimEMS, or
  1719.        5) an error occured during the allocation of the handle, or
  1720.        6) the value in ElementLen% was less than or equal to zero.
  1721.  
  1722.  
  1723.     When DimEMS creates an array, it stores information about that
  1724.     array in an internal table.  The handle returned by DimEMS is
  1725.     not a "true" EMS handle, but actually refers to a location in
  1726.     the table where information about an array can be found.
  1727.  
  1728.     The values of FirstIndex% and LastIndex% are limited to the
  1729.     range of a signed integer.  That range is from -32768 to 32767.
  1730.     The largest possible size you may designate for an individual
  1731.     element in an EMS array is 32767 bytes.
  1732.  
  1733.     If ElementLen% is less than or equal to zero, DimEMS will
  1734.     generate a non-standard error code of -4 and a handle of zero.
  1735.  
  1736.     If FirstIndex% is greater than LastIndex%, DimEMS will
  1737.     automatically correct their order, using LastIndex% as the first
  1738.     element in the array and FirstIndex% as the last element.
  1739.  
  1740.     Unlike BASIC, which initializes array elements to zero, the
  1741.     initial values of the elements in EMS arrays are unpredictable.
  1742.  
  1743.     EMS memory can only be allocated in multiples of 16K bytes
  1744.     (known as pages), so DimEMS must allocate the minimum number of
  1745.     16K pages needed to hold the requested number of elements.  For
  1746.     more information, see ABOUT EXPANDED MEMORY in MAXLIB.DOC.
  1747.  
  1748.     See also RedimEMS.
  1749.  
  1750.  
  1751.  
  1752.  
  1753.     EraseEMS
  1754.     -----------------------------------------------------------------
  1755.  
  1756.     DECLARE SUB EraseEMS (Handle%)
  1757.  
  1758.     Parameters: Handle% = handle of EMS array to erase
  1759.  
  1760.  
  1761.     This routine erases a single array in EMS memory.  The array is
  1762.     designated by Handle%.  When an EMS array is erased, the
  1763.     expanded memory it occupied is freed for further use.  EraseEMS
  1764.     will also remove the entry for Handle% from the internal table
  1765.     of array information maintained by the MAXArray routines.
  1766.  
  1767.  
  1768.         EraseEMS Handle%
  1769.  
  1770.  
  1771.     The above code erases the array designated by Handle%.
  1772.  
  1773.     The data in an erased array cannot be retrieved.  For that
  1774.     reason you should be cautious when calling EraseEMS.
  1775.  
  1776.     This routine may generate a non-standard error code of -3, if
  1777.     the Handle% parameter you pass it is an invalid handle.
  1778.  
  1779.     See also DimEMS, ClearEMS.
  1780.  
  1781.  
  1782.  
  1783.  
  1784.     ErrorCode
  1785.     -----------------------------------------------------------------
  1786.  
  1787.     DECLARE FUNCTION ErrorCode% ()
  1788.  
  1789.     Parameters: none
  1790.  
  1791.  
  1792.     This routine returns the error code stored in an internal
  1793.     variable.  This variable always reports the most recent error
  1794.     that took place during any call to any MAXLIB For PB routine.
  1795.     If no error has occured, ErrorCode% returns a zero.
  1796.  
  1797.     However, if an error does take place, every subsequent call to
  1798.     ErrorCode% will continue to report the same error until one of
  1799.     two things happens:
  1800.  
  1801.        1) another, different error takes place, or
  1802.        2) your program calls SetErrorCode to reset the error code.
  1803.  
  1804.  
  1805.     ErrorCode% may return some non-standard error codes (-1 to -4)
  1806.     under certain conditions.  For more information see HANDLING
  1807.     ERRORS in MAXLIB.DOC and the file ERRCODE.LST.
  1808.  
  1809.     See also SetErrorCode.
  1810.  
  1811.  
  1812.  
  1813.  
  1814.     FileInEMS
  1815.     -----------------------------------------------------------------
  1816.  
  1817.     DECLARE SUB FileInEMS (DOSHandle%, EMSHandle%)
  1818.  
  1819.     Parameters:  DOSHandle% = DOS handle of the file to copy into array
  1820.                  EMSHandle% = handle of the array to copy file into
  1821.  
  1822.  
  1823.     This routine is designed to load data from a disk file into an
  1824.     array in EMS memory.  Before calling FileInEMS, you must open
  1825.     the disk file and get its DOS file handle (which is different
  1826.     from its file number in BASIC).
  1827.  
  1828.  
  1829.        FileNum% = FREEFILE
  1830.        OPEN FileName$ FOR BINARY AS FileNum%
  1831.        DOSHandle% = FILEATTR(FileNum%, 2)    'FILEATTR gets DOS handle
  1832.        Records% = LOF(FileNum%) \ RecordLength%
  1833.  
  1834.        EMSHandle% = DimEMS%(1, Records%, RecordLength%)
  1835.        FileInEMS DOSHandle%, EMSHandle%
  1836.        CLOSE FileNum%
  1837.  
  1838.  
  1839.     The example code above opens a BASIC file, gets its DOS handle,
  1840.     calculates the number of array elements needed to hold the
  1841.     entire file (based on a known record length).  It then
  1842.     dimensions an EMS array of the correct size and copies the file
  1843.     into it using FileInEMS.
  1844.  
  1845.     FileInEMS writes as many bytes from the file into the EMS array
  1846.     as the size of the array.  Normally, the file and the array you
  1847.     dimension will be the same size.
  1848.  
  1849.     If the array size is smaller than the file size, FileInEMS will
  1850.     write as many bytes into the array as it will hold, then stop
  1851.     reading from the file.  If the array size is larger than the
  1852.     file size, FileInEMS will write the entire file into the array
  1853.     and stop, so that the unfilled elements in the array will keep
  1854.     the values they held before you called FileInEMS.
  1855.  
  1856.     FileInEMS will read from the file, starting at the current
  1857.     position of the file pointer.  For more information about file
  1858.     pointers, see the ABOUT FILE POINTERS chapter in MAXLIB.DOC.
  1859.  
  1860.     FileInEMS requires that the data in the file it is reading has
  1861.     no gaps or discontinuities.  Files saved with FileOutEMS will
  1862.     meet this requirement.  Files saved with PutX from a HUGE array
  1863.     may not meet this requirement.  For details, see AVOIDING
  1864.     PROBLEMS WITH HUGE ARRAYS in MAXLIB.DOC.
  1865.  
  1866.     Because FileInEMS accesses a disk drive it includes critical
  1867.     error trapping.  For more information, see HANDLING ERRORS in
  1868.     MAXLIB.DOC.
  1869.  
  1870.     This routine may generate a non-standard error code of -3, if
  1871.     the EMSHandle% parameter you pass it is an invalid handle.
  1872.  
  1873.     See also FileOutEMS.
  1874.  
  1875.  
  1876.  
  1877.  
  1878.     FileOutEMS
  1879.     -----------------------------------------------------------------
  1880.  
  1881.     DECLARE SUB FileOutEMS (DOSHandle%, EMSHandle%)
  1882.  
  1883.     Parameters: DOSHandle% = DOS handle of file to copy array into
  1884.                 EMSHandle% = handle of an array to copy into a file
  1885.  
  1886.  
  1887.     This routine is designed to write data from an EMS array into a
  1888.     disk file.  Before calling FileOutEMS, you must open the file
  1889.     and get its DOS file handle (which is different from its file
  1890.     number in BASIC).
  1891.  
  1892.  
  1893.        EMSHandle% = DimEMS%(1, 1000, 32)    'dim 32000 byte array
  1894.        .
  1895.        .
  1896.        FileNum% = FREEFILE
  1897.        OPEN FileName$ FOR BINARY AS FileNum%
  1898.        DOSHandle% = FILEATTR(FileNum%, 2)   'FILEATTR gets DOS handle
  1899.        FileOutEMS DOSHandle%, EMSHandle%    'write 32000 bytes
  1900.        CLOSE FileNum%
  1901.  
  1902.  
  1903.     The example code above dimensions an EMS array, then it opens a
  1904.     binary file, gets its DOS handle, and copies the EMS array into
  1905.     it using FileOutEMS. Then it closes the file.
  1906.  
  1907.     FileOutEMS calculates the number of bytes to write to the file,
  1908.     based on the size of the array.  The entire array will be
  1909.     written to the file starting at the current position of the file
  1910.     pointer.  If the file pointer is midway into the file, that is
  1911.     where FileInEMS will start writing.  For more information about
  1912.     file pointers, see ABOUT FILE POINTERS in MAXLIB.DOC.
  1913.  
  1914.     Because FileOutEMS accesses a disk drive it includes critical
  1915.     error trapping.  If a critical error takes place during a call
  1916.     to FileOutEMS, the error will be trapped and reported through
  1917.     ErrorCode%.  For more information, see HANDLING ERRORS in
  1918.     MAXLIB.DOC.
  1919.  
  1920.     This routine may generate a non-standard error code of -3, if
  1921.     the EMSHandle% parameter you pass it is an invalid handle.
  1922.  
  1923.     See also FileInEMS.
  1924.  
  1925.  
  1926.  
  1927.  
  1928.     HandlesEMS
  1929.     -----------------------------------------------------------------
  1930.  
  1931.     DECLARE FUNCTION HandlesEMS% ()
  1932.  
  1933.     Parameters: none
  1934.  
  1935.  
  1936.     The number of arrays DimEMS% can dimension at one time is
  1937.     limited to the number of entries in an internal table of array
  1938.     information it maintains.  HandlesEMS% reports the number of
  1939.     unused entries in that table.
  1940.  
  1941.     Each time you dimension an array, the number reported by
  1942.     HandlesEMS% will decrease by 1. Each time you erase an array
  1943.     the number reported by HandlesEMS% will increase by 1.
  1944.  
  1945.     HandlesEMS% will never report a number greater than 32, which is
  1946.     the largest size table InitMAXArray can initialize.
  1947.  
  1948.     When HandlesEMS% reports a zero, no handles are available and no
  1949.     further EMS arrays can dimensioned, even if expanded memory is
  1950.     available.  Both a handle and expanded memory must be available
  1951.     before DimEMS can dimension an array.
  1952.  
  1953.     See also BytesFreeEMS&.
  1954.  
  1955.  
  1956.  
  1957.  
  1958.     InEMS
  1959.     -----------------------------------------------------------------
  1960.  
  1961.     DECLARE SUB InEMS (Handle%, ToElement%, FromVariable AS ANY)
  1962.  
  1963.  
  1964.     Parameters:  Handle% = handle of the array holding ToElement%
  1965.                  ToElement% = index of the array element to write to
  1966.                  FromVariable = a variable of same type as the array
  1967.  
  1968.  
  1969.     This routine writes the contents of the variable FromVariable
  1970.     into the array element ToElement%.  The following snippets of
  1971.     code are comparable:
  1972.  
  1973.  
  1974.       DIM MyArray (1:2000) AS LONG   'dim it for long integers
  1975.       MyArray(1) = LongVal&          'put LongVal& in element 1
  1976.  
  1977.       MyArray% = DimEMS(1, 2000, 4)  'dim it for long integers
  1978.       InEMS MyArray%, 1, LongVal&    'put LongVal& in element 1
  1979.  
  1980.  
  1981.     InEMS assumes FromVariable is of the same length as ToElement.
  1982.     If FromVariable has fewer bytes than ToElement, some bytes that
  1983.     lie beyond FromVariable in memory will be written into
  1984.     ToElement.  If FromVariable has more bytes than ToElement, not
  1985.     all of FromVariable will be written into ToElement.
  1986.  
  1987.     If you pass a ToElement% which is outside the bounds of the
  1988.     array designated by Handle%, InEMS will return without taking
  1989.     any action, and a non-standard error code (-2) will be reported
  1990.     by your next call to ErrorCode%.
  1991.  
  1992.     InEMS is not suitable for manipulating variable-length strings
  1993.     or flex strings.  If you try to write such a string, only the
  1994.     two-byte string handle will be written into EMS memory, not the
  1995.     string data.
  1996.  
  1997.     This routine may generate a non-standard error code of -3, if
  1998.     the Handle% parameter you pass it is an invalid handle.
  1999.  
  2000.     NOTE: When a parameter is declared AS ANY it must be passed as a
  2001.     variable.  If you pass an equation, constant or literal value,
  2002.     the compiler will report Error 426: Variable expected.
  2003.  
  2004.     See also OutEMS, DimEMS.
  2005.  
  2006.  
  2007.  
  2008.  
  2009.     InitMAXArray
  2010.     -----------------------------------------------------------------
  2011.  
  2012.     DECLARE SUB InitMAXArray ()
  2013.  
  2014.     Parameters: none
  2015.  
  2016.  
  2017.     This routine initializes all the other routines in MAXArray.  It
  2018.     must be called once, before calling any other routine.  One call
  2019.     to InitMAXArray is enough.  Further calls will return with no
  2020.     action taken.
  2021.  
  2022.     When called, InitMAXArray looks for an EMM driver on the host
  2023.     computer.  If no EMM driver is found, further calls to MAXArray
  2024.     routines will return with no action taken.
  2025.  
  2026.     To find out whether InitMAXArray located an EMM driver, call
  2027.     VersionEMS% directly after calling InitMAXArray.  If no driver
  2028.     was found, VersionEMS% will return a zero.
  2029.  
  2030.     If an EMM driver was found, InitMAXArray looks at how many pages
  2031.     of memory and how many handles are available.  If the EMM driver
  2032.     is prior to version 4.0, the number of handles must be arrived
  2033.     at through guesswork and may be wrong.
  2034.  
  2035.     By default, InitMAXArray creates an internal table with 32
  2036.     entries.  This table is where DimEMS will store information
  2037.     about each array you dimension.  The maximum number of EMS
  2038.     arrays you can dimension at one time is limited to the number of
  2039.     entries in this internal table.  The table will have fewer than
  2040.     32 entries under the following conditions:
  2041.  
  2042.        1) InitMAXArray finds fewer than 32 free handles, or
  2043.        2) it finds fewer than 32 free pages of EMS memory.
  2044.  
  2045.     In such cases the table will be initialized with only enough
  2046.     entries to hold the smaller of these two resources.
  2047.  
  2048.     If you wish to know the size of the table, call HandlesEMS%
  2049.     immediately after calling InitMAXArray.  HandlesEMS% will return
  2050.     the number of unused entries in the table, as an integer.
  2051.  
  2052.     Lastly, InitMAXArray calls the internal PowerBASIC routine
  2053.     called SetOnExit to register ClearEMS as part of your program's
  2054.     exit code.  See ClearEMS for details.
  2055.  
  2056.  
  2057.  
  2058.  
  2059.  
  2060.     LBoundEMS
  2061.     -----------------------------------------------------------------
  2062.  
  2063.     DECLARE FUNCTION LBoundEMS% (Handle%)
  2064.  
  2065.     Parameters: Handle% = handle of array whose lower bound you want
  2066.  
  2067.  
  2068.     This routine is like LBOUND in BASIC.  It returns the index
  2069.     number of the first element of the EMS array designated by
  2070.     Handle%.
  2071.  
  2072.  
  2073.         FirstElem% = LBoundEMS%(MyArray%)
  2074.  
  2075.  
  2076.     The above code returns the number of the first element in the
  2077.     EMS array designated by the handle MyArray%.
  2078.  
  2079.     This routine may generate a non-standard error code of -3, if
  2080.     the EMSHandle% parameter you pass it is an invalid handle.
  2081.  
  2082.     See also UBoundEMS.
  2083.  
  2084.  
  2085.  
  2086.  
  2087.  
  2088.     OutEMS
  2089.     -----------------------------------------------------------------
  2090.  
  2091.     DECLARE SUB OutEMS (ToVariable AS ANY, Handle%, FromElement%)
  2092.  
  2093.  
  2094.     Parameters:  ToVariable = variable of the same type as the array
  2095.                  Handle% = handle of the array holding FromElement%
  2096.                  FromElement% = index of array element to write from
  2097.  
  2098.  
  2099.  
  2100.     This routine writes the array element FromElement% into the
  2101.     variable ToVariable.  The following two lines of code are
  2102.     comparable:
  2103.  
  2104.  
  2105.       LongVal& = MyArray&(1)
  2106.       OutEMS LongVal&, MyArray%, 1
  2107.  
  2108.  
  2109.     OutEMS assumes ToVariable is the same length as FromElement.  If
  2110.     ToVariable has more bytes than FromElement, a number of bytes at
  2111.     the end of ToVariable will be left intact.
  2112.  
  2113.     WARNING: If ToVariable has fewer bytes than FromElement%, OutEMS
  2114.     will overwrite some of the bytes that lie beyond ToVariable in
  2115.     memory, corrupting them and probably losing data.
  2116.  
  2117.     If you pass a FromElement% which is outside the bounds of the
  2118.     array designated by Handle%, OutEMS will return without taking
  2119.     any action, and a non-standard error code (-2) will be reported
  2120.     by your next call to ErrorCode%.
  2121.  
  2122.     This routine may generate a non-standard error code of -3, if
  2123.     the Handle% parameter you pass it is an invalid handle.
  2124.  
  2125.     NOTE: When a parameter is declared AS ANY it must be passed as a
  2126.     variable.  If you pass an equation, constant or literal value,
  2127.     the compiler will report Error 426: Variable expected.
  2128.  
  2129.     See also InEMS, DimEMS.
  2130.  
  2131.  
  2132.  
  2133.  
  2134.     RedimEMS
  2135.     -----------------------------------------------------------------
  2136.  
  2137.     DECLARE SUB RedimEMS (Handle%, LastIndex%)
  2138.  
  2139.  
  2140.     Parameters:  Handle% = handle of the array to redimension
  2141.                  LastIndex% = new last element number in the array
  2142.  
  2143.  
  2144.     This routine redimensions the array designated by Handle% to the
  2145.     new size indicated by LastIndex%.  The redimensioned array keeps
  2146.     the same handle, the same first index and the same element
  2147.     length it had when it was originally dimensioned.  If you
  2148.     require these to change, you must dimension a new array.
  2149.  
  2150.     LastIndex% may be smaller than or larger than the current last
  2151.     element number, making the array either smaller or larger.  If
  2152.     the array becomes larger, all the data is preserved.  If the
  2153.     array becomes smaller, all the data up to the new last element
  2154.     is preserved and data above that point becomes unrecoverable.
  2155.  
  2156.  
  2157.         Handle% = DimEMS%(1001, 2000, 32)   'dimension 32000 bytes
  2158.         RedimEMS Handle%, 3000              'redim to 64000 bytes
  2159.  
  2160.  
  2161.     The above code dimensions an EMS array of 1000 elements, where
  2162.     the first index is 1001 and the last is 2000.  Then it
  2163.     redimensions it with 2000 elements, where the first index is
  2164.     1001 and the last is 3000.
  2165.  
  2166.     RedimEMS requires an EMM driver of v4.0 (or later).  If the EMM
  2167.     driver is v3.x, RedimEMS will return without taking any action.
  2168.     You can check the EMM version using VersionEMS.
  2169.  
  2170.     Unlike REDIM in BASIC, you cannot use RedimEMS to dimension an
  2171.     EMS array that has not been dimensioned.  All EMS arrays must be
  2172.     dimensioned with DimEMS before they can be redimensioned.
  2173.  
  2174.     If you redimension an array to make it larger, the initial
  2175.     values in the added elements will be unpredictable.
  2176.  
  2177.     RedimEMS will generate a non-standard error code of -3, if the
  2178.     Handle% parameter you pass it is an invalid handle.  It will
  2179.     generate a non-standard error code of -2, if the new LastIndex%
  2180.     is less than the FirstIndex% of the array.
  2181.  
  2182.     See also DimEMS, VersionEMS.
  2183.  
  2184.  
  2185.  
  2186.  
  2187.     SetErrorCode
  2188.     -----------------------------------------------------------------
  2189.  
  2190.     DECLARE SUB SetErrorCode (ErrorCode%)
  2191.  
  2192.     Parameters:  ErrorCode% = new value for internal error code
  2193.  
  2194.  
  2195.     This routine resets MAXLIB's internal error code variable to the
  2196.     value passed in the ErrorCode% parameter.
  2197.  
  2198.  
  2199.         SetErrorCode 0
  2200.  
  2201.  
  2202.     The above code resets the internal error code variable to zero.
  2203.  
  2204.     For more information on error handling, see HANDLING ERRORS in
  2205.     MAXLIB.DOC.
  2206.  
  2207.     See also ErrorCode.
  2208.  
  2209.  
  2210.  
  2211.  
  2212.     UBoundEMS
  2213.     -----------------------------------------------------------------
  2214.  
  2215.     DECLARE FUNCTION UBoundEMS% (Handle%)
  2216.  
  2217.     Parameters: Handle% = handle of array whose upper bound you want
  2218.  
  2219.  
  2220.     This routine is like UBOUND in BASIC.  It returns the index of
  2221.     the last element in the EMS array designated by Handle%
  2222.  
  2223.  
  2224.         LastElem% = UBoundEMS%(MyArray%)
  2225.  
  2226.  
  2227.     The above code returns the index of the last element in the EMS
  2228.     array designated by the handle MyArray%.
  2229.  
  2230.     This routine may generate a non-standard error code of -3, if
  2231.     the EMSHandle% parameter you pass it is an invalid handle.
  2232.  
  2233.     See also LBoundEMS%.
  2234.  
  2235.  
  2236.  
  2237.  
  2238.     VersionEMS
  2239.     -----------------------------------------------------------------
  2240.  
  2241.     DECLARE FUNCTION VersionEMS% ()
  2242.  
  2243.     Parameters: none
  2244.  
  2245.  
  2246.     This routine returns the version number of the EMM driver, as an
  2247.     integer.  For example, version 4.0 would be returned as 40, and
  2248.     version 3.2 would be returned as 32.  If no EMM driver was
  2249.     detected by InitMAXArray, VersionEMS% returns a zero.
  2250.  
  2251.  
  2252.         DriverVer% = VersionEMS%
  2253.  
  2254.  
  2255.     Except for RedimEMS, all the routines in MAXArray should work
  2256.     with every version of EMM driver software.  RedimEMS requires
  2257.     version 4.0.
  2258.  
  2259.  
  2260.  
  2261.     ********************************************************************
  2262.  
  2263.                      END OF SECTION TWO:  MAXARRAY
  2264.  
  2265.     ********************************************************************
  2266.  
  2267.